/* 
学习装饰器语法
*/



/* 
https://caniuse.com/?search=Decorator

*/


/* 
Targtet 就是我们装饰器修饰的这个类 装饰器的底层转换类似如下：

T = T(Person);


*/
function T(prefix) {

    console.log('T call--------------------->');

    return function (v2Prefix) {
        return function (Targtet) {
            /* 可以对这个类进行扩充形成 对象的原型的方法和属性 */
            Targtet.prototype.type = 'human';
            Targtet.prototype.say = function () {
                console.log(prefix + ' say hello ' + v2Prefix);

            }

            /* 扩展静态的属性和方法 */
            Targtet.isType = 'Person Human';
            Targtet.fn = function () {
                console.log('fn call...');

            }

        }
    }
}

/* 装饰器还可以叠加，叠罗汉，汉罗塔，语法是从上到下叠罗汉，执行的时候是从下到上调用。
- https://nestjs.bootcss.com/modules


import { Module, Global } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';

@Global()
@Module({
  controllers: [CatsController],
  providers: [CatsService],
  exports: [CatsService],
})
export class CatsModule {}

底层有点类似：  Person = T1(T('[-_-]')('([+_+])')(Person));
    > https://www.jianshu.com/p/6319f4e5e3b0
*/

function T1(Target) {
    console.log('T1 call--------------------->');
    Target.prototype.run = function () {
        console.log('i can run!!!');

    }

}

/* 
    Reflect
    Proxy

*/
/* Object.defineProperty(p1, 'name', {
    writable: true, // 配置对象  name 是否修改 true 可以 false 不可以 
    enumerable: true, // 配置对象 name 是否 是否被遍历 for in (不支持 for of) [Symbol.iterator]
    configurable: true, // 配置对象 name 是否 可以被删除 delete
}); */

/* 
enumerable 遍历
 */
function enumerable(value) {
    /* 
        target 类
        key 方法名称
        descriptor 方法的属性描述
    */
    return function (target, key, descriptor) {
        descriptor.enumerable = value;
        return descriptor;
    };
}


function writable(value) {
    /* 
        target 类
        key 方法名称
        descriptor 方法的属性描述
    */
    return function (target, key, descriptor) {
        descriptor.writable = value;
        return descriptor;
    };
}



@T1
@T('[-_-]')('([+_+])')
class Person {

    @enumerable(false)
    age = 12;

    /* name 属性是不可以被修改和枚举（遍历） */

    @writable(true)
    @enumerable(false)
    name = '';

    constructor(name) {
        this.name = name;
    }

    sing() {
        console.log('sing...');
    }

}

const p1 = new Person('andy');

p1.sing();
console.log(p1.age);
console.log(p1.name);


console.log('遍历对象 for in');
for (let key in p1) {
    console.log(key);
}

p1.name = 'mark';

console.log('p1.name:', p1.name);